package com.korustar.autumnal.spring;


import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;

import com.korustar.autumnal.reflect.StaticFieldReflection;
import com.korustar.autumnal.reflect.StaticMethodReflection;

/**
 * helpers for working with BeanDefinitions
 * 
 * @author amir
 *
 */
public class BeanDefinitionUtil {
	private static final Logger LOGGER = LoggerFactory.getLogger( BeanDefinitionUtil.class );
	
	public static String getTypeAsText(BeanDefinition beanDefinition) {
		//factory bean doesn't specify bean type!!
		if(beanDefinition.getFactoryMethodName()!=null) { 
			String beanClassName = beanDefinition.getBeanClassName();
			String factoryMethodName = beanDefinition.getFactoryMethodName();
			ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues();
			int argumentCount = constructorArgumentValues.getArgumentCount();
			Class<?>[] argTypes= new Class<?>[argumentCount];
			for(int i=0;i<argumentCount;i++) {
				//argTypes[i]= guessType(constructorArgumentValues.);
				//TODO: type guessing!
				argTypes[i]= String.class;
			}
			Class<?> returnType = StaticMethodReflection.getReturnType(beanClassName, factoryMethodName, argTypes);
			if(returnType!=null) {
				return returnType.getCanonicalName();
			}
			//Fall back to 'Object' ... 
			return Object.class.getCanonicalName();
		} else {
			return beanDefinition.getBeanClassName();
		}
	}
	
	public static final String SPRINGFRAMEWORK_FIELD_RETRIEVING_FACTORY_BEAN = "org.springframework.beans.factory.config.FieldRetrievingFactoryBean";
	public static final String SPRINGFRAMEWORK_FIELD_RETRIEVING_FACTORY_BEAN_STATIC_FIELD = "staticField";
	public static final String SPRINGFRAMEWORK_PROPERTY_PLACEHOLDER_CONFIGURER = "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer";

	
	
	
	public static Class<?> guessType(BeanDefinition beanDefinition) {
		if(SPRINGFRAMEWORK_FIELD_RETRIEVING_FACTORY_BEAN.equals(beanDefinition.getBeanClassName()))
		{
			MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
			List<PropertyValue> propertyValueList = propertyValues.getPropertyValueList();
			for(PropertyValue pv : propertyValueList) {
				if(SPRINGFRAMEWORK_FIELD_RETRIEVING_FACTORY_BEAN_STATIC_FIELD.equals(pv.getName()))
				{
					LOGGER.info("staticField property value: {} : {}", pv.getName(), pv.getValue() );
					String staticField = (String) pv.getValue();
					if(StaticFieldReflection.isStaticFieldOnClasspath(staticField)) {
						return StaticFieldReflection.getStaticFieldType(staticField);
					}
				}
			}
			//return gbd.getBeanClass();
		}
		//TODO!!!
		LOGGER.warn("Guessing String type");
		//fuggit!
		return String.class;
	}
	
	@SuppressWarnings("unused")
	private static void validateConstructorArgsAreReady(BeanDefinition beanDefinition) {
		//beanDefinition
		ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues();
		Map<Integer, ValueHolder> indexedArgumentValues = constructorArgumentValues.getIndexedArgumentValues();
		for(Integer x : indexedArgumentValues.keySet()) {
			ValueHolder valueHolder = indexedArgumentValues.get(x);
			LOGGER.debug("constructor arg val: "+valueHolder.getValue() );
			//if(valueHolder.)
			
			
		}
		List<ValueHolder> genericArgumentValues = constructorArgumentValues.getGenericArgumentValues();
		for(ValueHolder valueHolder : genericArgumentValues) {
			LOGGER.debug("constructor arg: {} val: {}",valueHolder.getName(), valueHolder.getValue() );
		}
	}
}
